#include <cstdlib>
#include <ctime>
#include <cmath>

#include "SimulatedAnnealing.h"

using namespace std;

void SimulatedAnnealing::simulate() {
    vector<int> states;
    bool changedState = true;
    iterations = 0;
    for ( vector<float>::const_iterator temp = tempVector_.begin();
            temp != tempVector_.end(); ++temp ) {
        ++iterations;
        float T = *temp;

        if ( T == 0 || problem_->isSolved() ) {
            return;
        }

        if ( changedState ) {
            problem_->generateStates ( states );
        }

        int nextStateNr = states.at ( rand() % states.size() );

        float dEnergy = problem_->energy ( nextStateNr ) - problem_->currentEnergy();

        changedState = true;

        if ( dEnergy > 0 ) {
            problem_->setState ( nextStateNr );
        } else {
            float probability = exp ( dEnergy / T );

            if ( ( rand() % 1000 ) < ( probability * 1000 ) ) {
                problem_->setState ( nextStateNr );
            } else {
                changedState = false;
            }
        }
    }
}

void SimulatedAnnealing::generateTemperatures ( std::vector< float >& temp_vector, float start, float interval ) {
    temp_vector.clear();
    while(start > 0) {
        temp_vector.push_back(start);
        start -= interval;
    }
    temp_vector.push_back(0);
}

